package com.jiangyg.devtools.execute.code;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.InputValidator;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.ui.components.JBScrollPane;
import com.jiangyg.devtools.entity.code.BeanDefinition;
import com.jiangyg.devtools.entity.code.CodeFile;
import com.jiangyg.devtools.entity.code.TemplateDefinition;
import com.jiangyg.devtools.toolkit.AwtUtils;
import com.jiangyg.devtools.toolkit.CamelCaseUtils;
import com.jiangyg.devtools.toolkit.CommonUtils;
import com.jiangyg.devtools.toolkit.TemplateUtils;
import com.jiangyg.devtools.ui.AbstractDialogWrapper;
import com.jiangyg.devtools.ui.table.AbstractEditableTableModel;
import com.jiangyg.devtools.ui.table.EditableTable;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 类描述：生成代码
 *
 * @author jiangyg
 * @date 2023-08-31
 */
public class CreateCodeActionImpl {

    private final Project project;

    private final BeanDefinition definition;

    private final List<TemplateDefinition> templates;

    public CreateCodeActionImpl(Project project,
                                BeanDefinition definition,
                                List<TemplateDefinition> templates) {
        this.project = project;
        this.definition = definition;
        this.templates = templates;
    }

    public void exec() {
        // 获取输入Bean的名称
        if (!setBeanName()) {
            return;
        }
        // 生成代码之前的校验
        if (!checkCreateCode()) {
            return;
        }
        // 是否确认生成代码提示
        new CodeFileListDialogWrapper().show();

//        if (!confirmCreateCodeTip()) {
//            return;
//        }
//        // 生成提示
//        for (TemplateDefinition template : templates) {
//            final String packagePath = CommonUtils.getPackagePath(project, template.getPath());
//            try {
//                final String codeString = TemplateUtils.template(template.getName(), template.getContent(), definition);
//                Files.writeString(Path.of(packagePath + "asd.java"), codeString, StandardCharsets.UTF_8);
//            } catch (Exception ex) {
//                throw new DevtoolsException("生成模板出错", ex);
//            }
//        }
    }

    /**
     * 功能描述：设置Bean的名称
     *
     * @return 是否继续
     */
    private boolean setBeanName() {
        String beanName = definition.getName();
        if (StringUtils.isBlank(beanName)) {
            beanName = this.getBeanName();
            if (StringUtils.isBlank(beanName)) {
                return false;
            }
            beanName = CamelCaseUtils.underlineToCamel(beanName);
            beanName = StringUtils.capitalize(beanName);
            definition.setName(beanName);
        }
        return !StringUtils.isBlank(definition.getName());
    }

    /**
     * 功能描述：生成代码之前的校验
     *
     * @return 是否校验通过
     */
    private boolean checkCreateCode() {
        // 校验是否存在选中模板
        if (templates.stream().noneMatch(TemplateDefinition::isSelected)) {
            AwtUtils.errorTip("没有要生成的模板！");
            return false;
        }
        // 选中模板是否配置生成路径
        for (TemplateDefinition template : templates) {
            if (StringUtils.isBlank(template.getPath())) {
                final String errMsg = String.format("模板[%s]没有配置包路径！", template.getName());
                AwtUtils.errorTip(errMsg);
                return false;
            }
        }
        return true;
    }

    /**
     * 功能描述：获取Bean的名称
     *
     * @return 名称
     */
    private String getBeanName() {
        return Messages.showInputDialog("Bean名称：", "请输入Bean名称", null, definition.getName(), new InputValidator() {

            @Override
            public boolean checkInput(@NlsSafe String inputString) {
                return StringUtils.isNotBlank(inputString) && Pattern.matches("[a-zA-Z]\\w+", inputString);
            }

            @Override
            public boolean canClose(@NlsSafe String inputString) {
                return StringUtils.isNotBlank(inputString);
            }

        });
    }

    /**
     * 类描述：代码文件列表窗口
     *
     * @author jiangyg
     * @date 2023-09-02
     */
    private final class CodeFileListDialogWrapper extends AbstractDialogWrapper {

        private final MyTableModel tableModel = new MyTableModel();

        private CodeFileListDialogWrapper() {
            super(CreateCodeActionImpl.this.project);
            init();
            this.setTitle("代码生成文件列表");
            this.setSizeByRatio(0.6, 0.5);
            this.setOKButtonText("确认生成代码");
            this.setCancelButtonText("取消生成代码");
        }

        @Override
        protected @NotNull JComponent createCenterPanel() {
            final EditableTable table = new EditableTable("create-code", tableModel, project);

            // 预生成默默搬内容
            for (TemplateDefinition template : templates) {
                final CodeFile codeFile = new CodeFile();

                codeFile.setSelected(template.isSelected());
                codeFile.setFileName(codeFileName(template));
                codeFile.setFileContent(codeFileContent(template));
                final String filePath = CommonUtils.getPackagePath(project, template.getPath());
                codeFile.setFilePath(filePath);

                tableModel.addRow(codeFile);
            }

            return new JBScrollPane(table);
        }

        @Override
        protected void doOKAction() {
            final List<CodeFile> dataList = tableModel.getDataList();

            // 校验
            if (CollectionUtils.isEmpty(dataList)) {
                AwtUtils.errorTip("没有要生成的代码文件！");
                return;
            }

            // 代码文件落地
            for (CodeFile codeFile : dataList) {
                try {
                    final Path path = Path.of(codeFile.getFilePath() + codeFile.getFileName());
                    Files.writeString(path, codeFile.getFileContent(), StandardCharsets.UTF_8);
                } catch (Exception ex) {
                    AwtUtils.errorTip(String.format("文件[%s]生成失败：%s", codeFile.getFileName(), ex.getMessage()));
                }
            }

            AwtUtils.successTip("代码生成成功！");

            super.doOKAction();
        }

        /**
         * 功能描述：生成文件名
         *
         * @param template 模板
         * @return 文件名
         */
        private String codeFileName(TemplateDefinition template) {
            try {
                return TemplateUtils.template(template.getName() + "-name", template.getFname(), definition);
            } catch (Exception ex) {
                return ex.toString();
            }
        }

        /**
         * 功能描述：生成代码内容
         *
         * @param template 模板
         * @return 代码内容
         */
        private String codeFileContent(TemplateDefinition template) {
            try {
                return TemplateUtils.template(template.getName() + "-content", template.getContent(), definition);
            } catch (Exception ex) {
                return ex.toString();
            }
        }

    }

    private static final class MyTableModel extends AbstractEditableTableModel<CodeFile> {

    }

}
